---
title: Business rules
summary: Business rules enforced during OnBaseKeywordSync processing.
status: draft
owner: Documents
last_reviewed: 2026-09-17
---

# Business rules

Every rule below is enforced in the executable; the argument container enforces none, because it declares no arguments. Three additional rules are inherited from `SAIF.Framework.Windows` and are included for completeness even though two of them are not reachable by this application.

---

## BR-OBKS-001 Asynchronous or synchronous update mode

| Field | Value |
| --- | --- |
| Statement | Updates are sent to OnBase asynchronously or synchronously according to `OnBaseKeywordSync.onbaseasync`; only the synchronous path yields a document handle. |
| Trigger | Start of `Execute()` |
| Enforcement | `OnBaseKeywordSyncRunner.Execute`, `OnBaseKeywordSyncClient.UpdateKeyword` |
| Origin | application |
| Outcome | `INS_RequestType_Collection` set to `ASYNCHRONOUS`/`SYNCHRONOUS`; async calls are fire-and-forget with no handle logged |
| Source | `OnBaseKeywordSync/OnBaseKeywordSyncRunner.cs`, `OnBaseKeywordSync/Services/OnBaseKeywordSyncClient.cs` |

---

## BR-OBKS-002 Invalid person keyword syncs cleared before the batch

| Field | Value |
| --- | --- |
| Statement | Keyword syncs whose `person_id` does not exist are cleared before the batch runs and are reported as not processed. |
| Trigger | Before retrieving unprocessed records |
| Enforcement | `OnBaseKeywordSyncRunner.ProcessInvalidKeywordSyncs`, `ImagingApiClient.ProcessInavlidPersonKeywordSyncs` |
| Origin | application |
| Outcome | Server-side clear; one log line per cleared record |
| Source | `OnBaseKeywordSync/OnBaseKeywordSyncRunner.cs`, `OnBaseKeywordSync/Services/ImagingApiClient.cs` |

---

## BR-OBKS-003 Unprocessed records processed in ascending Id order

| Field | Value |
| --- | --- |
| Statement | Unprocessed keyword syncs are processed in ascending `Id` order. |
| Trigger | After the invalid-sync clear |
| Enforcement | `OnBaseKeywordSyncRunner.Execute` (`OrderBy(x => x.Id)`) |
| Origin | application |
| Outcome | Deterministic, oldest-first processing |
| Source | `OnBaseKeywordSync/OnBaseKeywordSyncRunner.cs` |

---

## BR-OBKS-004 Document count gates whether a record is sent

| Field | Value |
| --- | --- |
| Statement | When document counting is enabled, a record is sent only if it has at least one document to update; when disabled, every record is sent without a count check. |
| Trigger | Per record |
| Enforcement | `KeywordUpdater.PerformUpdate` |
| Origin | application |
| Outcome | Send or skip decision with a logged reason |
| Source | `OnBaseKeywordSync/Services/KeywordUpdater.cs` |

---

## BR-OBKS-005 Equal prior and new values are not sent

| Field | Value |
| --- | --- |
| Statement | A record whose prior and new values are equal (case-insensitive) is not sent to OnBase. |
| Trigger | Per record, when the document-count branch does not already return true |
| Enforcement | `KeywordUpdater.PerformUpdate` |
| Origin | application |
| Outcome | Logged `"No updates will be sent to onbase because prior value and new value are the same"`. Ordering finding: because the document-count branch is evaluated first, a record whose values are identical is still sent when document counting is on and documents exist — this equality short-circuit only applies when document counting is off or no documents exist* |
| Source | `OnBaseKeywordSync/Services/KeywordUpdater.cs` |

---

## BR-OBKS-006 Trigger type and query keyword derived by precedence

| Field | Value |
| --- | --- |
| Statement | A keyword sync's trigger type and OnBase query keyword are derived by precedence: claim number, then person id, then policy number, then agency number, then group acronym. |
| Trigger | Whenever a record's type or key is needed |
| Enforcement | `ImageKeywordSync.TriggerType`, `ImageKeywordSyncExtensions`, `KeywordUpdateExtensions` |
| Origin | application |
| Outcome | Trigger type, output key, and `INS_QueryKeywordType` (`CLAIM NUMBER` / `POLICY NUMBER` / `AGENCY NUMBER` / `GROUP ACRONYM`) |
| Source | `OnBaseKeywordSync/Contracts/ImageKeywordSync.cs`, `OnBaseKeywordSync/Contracts/ImageKeywordSyncExtensions.cs`, `OnBaseKeywordSync/Contracts/KeywordUpdateExtensions.cs` |

---

## BR-OBKS-007 Empty new value applied as keyword deletion

| Field | Value |
| --- | --- |
| Statement | An empty new keyword value is applied to OnBase as a keyword deletion, not as a blank value. |
| Trigger | Building the keyword action |
| Enforcement | `OnBaseKeywordSyncClient.AddKeywordUpdateAction` |
| Origin | application |
| Outcome | `INS_Action = "DELETE"` with a null data value; otherwise `ADD` with the upper-cased value |
| Source | `OnBaseKeywordSync/Services/OnBaseKeywordSyncClient.cs` |

---

## BR-OBKS-008 Custom query selected from doc type group mapping

| Field | Value |
| --- | --- |
| Statement | The OnBase custom query is selected from the doc type group using the `OnBaseKeywordSync.customquerymappings` `DTG\|query` pairs (`~`-delimited). |
| Trigger | Building the E-Form payload |
| Enforcement | `OnBaseKeywordSyncClient.GetCustomQueryName` |
| Origin | application |
| Outcome | `INS_CustomQuery` set; an unmapped group throws `KeyNotFoundException` and aborts the run (exit code `5`) |
| Source | `OnBaseKeywordSync/Services/OnBaseKeywordSyncClient.cs` |

---

## BR-OBKS-009 Flag keyword translation

| Field | Value |
| --- | --- |
| Statement | Three keywords are translated to Y/N flags: `CLAIM EXPOSURE FLAG` is `Y` when the value is not `"0"`; `CLAIM SECURED FLAG` is `Y` when the value is `R` or `T`; `POLICY SECURED FLAG` is `Y` when the value is non-blank. All other keywords pass through unchanged. |
| Trigger | Every prior/new value resolution |
| Enforcement | `KeywordHelper.GetKeywordValue`, `KeywordHelper.BuildYesNoFlagTranslations` |
| Origin | application |
| Outcome | Normalized `Y`/`N` value sent to OnBase |
| Source | `OnBaseKeywordSync/Services/KeywordHelper.cs` |

---

## BR-OBKS-010 Every record marked processed after its update set completes

| Field | Value |
| --- | --- |
| Statement | Every record is marked processed after its update set completes — including records that were skipped and never sent to OnBase. |
| Trigger | After each record in the batch |
| Enforcement | `KeywordUpdater.RaiseOnBaseKeywordUpdateSetComplete` → `OnBaseKeywordSyncRunner.Updater_OnBaseKeywordUpdateSetComplete` → `ImagingApiClient.MarkKeywordSyncAsProcessed` |
| Origin | application |
| Outcome | `POST ImageKeywordSyncs/MarkProcessed?id={id}` |
| Source | `OnBaseKeywordSync/Services/KeywordUpdater.cs`, `OnBaseKeywordSync/OnBaseKeywordSyncRunner.cs`, `OnBaseKeywordSync/Services/ImagingApiClient.cs` |

---

## BR-OBKS-011 OnBase calls throttled by a sleep interval

| Field | Value |
| --- | --- |
| Statement | Calls to OnBase are throttled by sleeping `OnBaseKeywordSync.onbaseclientsleepmilliseconds` after each update when that value is greater than zero. |
| Trigger | After each OnBase call |
| Enforcement | `OnBaseKeywordSyncClient.UpdateKeyword` |
| Origin | application |
| Outcome | Thread sleep; a source comment states the service loses requests without it |
| Source | `OnBaseKeywordSync/Services/OnBaseKeywordSyncClient.cs` |

---

## BR-WIN-003 Invalid arguments halt the run

| Field | Value |
| --- | --- |
| Statement | Invalid arguments halt the run before application logic with exit code `1`.† |
| Trigger | Argument resolution |
| Enforcement | `ProgramRunnerBase.Run` (framework) |
| Origin | `SAIF.Framework.Windows` |
| Outcome | Not reachable here — no arguments are declared* |
| Source | — |

---

## BR-WIN-004 SaifConsoleException supplies its own exit code

| Field | Value |
| --- | --- |
| Statement | A `SaifConsoleException` supplies its own exit code.† |
| Trigger | Exception escapes the application |
| Enforcement | `ProgramRunnerBase.Run` (framework) |
| Origin | `SAIF.Framework.Windows` |
| Outcome | Not reachable here — no such exception is thrown |
| Source | — |

---

## BR-WIN-005 Unhandled exception yields exit code 5

| Field | Value |
| --- | --- |
| Statement | An unhandled non-`SaifConsoleException` exception yields exit code `5`.† |
| Trigger | Exception escapes `Execute()` |
| Enforcement | `ProgramRunnerBase.Run` (framework) |
| Origin | `SAIF.Framework.Windows` |
| Outcome | The only failure exit code this application produces |
| Source | `OnBaseKeywordSync/OnBaseKeywordSyncRunner.cs` |

---

## Related documentation
- [Application index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Run lifecycle](run-lifecycle.md)
- [Arguments](arguments.md)
- [Dependencies](dependencies.md)
- [Configuration](configuration.md)
- [Operations and processes](operations-processes.md)
- [Operational runbook](operational-runbook.md)
- [Tech debt](tech-debt.md)

> **Note:** Statements marked with `†` are derived from dependency library documentation via the Legends CLI. Statements marked with `*` were inferred from code structure or contextual evidence.

## Sources
- `OnBaseKeywordSync/OnBaseKeywordSyncRunner.cs`
- `OnBaseKeywordSync/Services/ImagingApiClient.cs`
- `OnBaseKeywordSync/Services/KeywordUpdater.cs`
- `OnBaseKeywordSync/Services/OnBaseKeywordSyncClient.cs`
- `OnBaseKeywordSync/Services/KeywordHelper.cs`
- `OnBaseKeywordSync/Contracts/ImageKeywordSync.cs`
- `OnBaseKeywordSync/Contracts/ImageKeywordSyncExtensions.cs`
- `OnBaseKeywordSync/Contracts/KeywordUpdateExtensions.cs`
